package com.mach.platform.sprider.dev;

import com.mach.platform.sprider.mail.MailOperation;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class DataHelper implements Runnable {

    private static final int READ_TIME_OUT = 1000;
    //邮件相关属性
    private static final String USER= "1499679282@qq.com";
    private static final String PASSWORD= "xiktpahnztyxjjbf";
    private static final String HOST= "smtp.qq.com";
    private static final String FROM= "1499679282@qq.com";
    private static final String TO= "1499679282@qq.com";   // 收件人
    private static final String SUBJECT = "郑州项目上传云数据警报";
    private String content;
    private Map<String,Long> timeStore = new HashMap<>();

    public static void main(String[] args) throws IOException, Exception {
        DataHelper dh = new DataHelper("192.168.3.90", 8002, 7);

        for (int i = 0; i < 1000; ++i) {
            byte[] result = dh.getDataRtu(
                    30001, 1,3);
            System.out.println(ByteUtil.getFloat(result, 3, 4, false));
        }


        byte[] dataBuf = new byte[20];

        byte[] nowBuf = ByteUtil.getBytes(System.currentTimeMillis());
        byte[] devIdBuf = ByteUtil.getBytes(101);
        byte[] collIdBuf = ByteUtil.getBytes(10);


//		DataHelper dh = new DataHelper("192.168.3.92",8000,1);
//
//		for(int i = 0; i < 10; ++i) {
//			byte[] result = dh.getData(40000, 4);
//		}
    }

    protected String ip;
    protected Integer port;
    protected Integer devID;
//	private Socket clientSk;
//	private InputStream cskIn;
//	private OutputStream cskOut;


    protected TcpWorker wk;

    public DataHelper(String ip, Integer port, Integer devID) {
        this.ip = ip;
        this.port = port;
        this.devID = devID;

        this.wk = TcpService.get().regWorkTcpWork(this.ip, this.port);
    }

    @Override


    public void run() {
        // TODO Auto-generated method stub

    }

//	synchronized private void reCon(){
//		this.clientSk = null ;
//		try {
//			this.clientSk = new Socket(this.ip, this.port);
//
//			this.clientSk.setSoTimeout(READ_TIME_OUT);
//
//			this.cskIn = clientSk.getInputStream();
//			this.cskOut = clientSk.getOutputStream();
//
//		}catch(Exception e) {
//			e.printStackTrace();
//		}
//	}
//	synchronized private void close(){
//		try {
//			this.clientSk.close();
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//	}

    public String getDevAddr() {
        return this.ip + ":" + this.port + ":" + this.devID;
    }

    public byte[] readSth(Integer addr, Integer num, Integer cmdCode) {
        byte[] result = null;


        byte[] repData = new byte[0];
        try {
            repData = this.getDataRtu(addr, num, cmdCode);
//            if(repData.length <1)return null;
//            byte[] data = ByteUtil.subData(repData,3,4);
//            data = ByteUtil.reverse(data);
            result = repData;
        } catch (Exception e) {
//            e.printStackTrace();
            System.out.println("excep IP:" + this.ip + ":" + this.port + e.getMessage());
        }
        return result;
    }

    public byte[] readSthTcp(Integer addr, Integer num, Integer cmdCode) {
        byte[] result = null;


        byte[] repData = new byte[0];
        try {
            repData = this.getDataTcp(addr, num,cmdCode);
//            if(repData.length <1)return null;
//            byte[] data = ByteUtil.subData(repData,3,4);
//            data = ByteUtil.reverse(data);
            result = repData;
        } catch (Exception e) {
//            e.printStackTrace();
            System.out.println("excep IP:" + this.ip + ":" + this.port + e.getMessage());
        }
        return result;
    }

    public byte[] getDataRtu(Integer startAddr, Integer len) throws IOException {
        return getDataRtu(startAddr, len, 3);
    }


    public byte[] getDataRtu(Integer startAddr, Integer len, Integer cmdCode) throws IOException {
        IntNum startAddrNum = new IntNum(startAddr);
        IntNum lenNUmum = new IntNum(len);

        byte[] result = {};

        byte[] sendData = new byte[6];
        sendData[0] = this.devID.byteValue();
        sendData[1] = cmdCode.byteValue();
        sendData[2] = startAddrNum.h2();
        sendData[3] = startAddrNum.l2();
        sendData[4] = lenNUmum.h2();
        sendData[5] = lenNUmum.l2();

        byte[] sendDataHasCRC = UU.setCrc16Btye(sendData);

        System.out.print("devId:" + this.getDevAddr() + " <-- ");//debug log
        UU.printData(sendDataHasCRC);   //输出指令
        //		this.wk.send(sendData);
//		result = this.wk.read4TimeOut();

        result = this.wk.command(sendDataHasCRC);
        System.out.print("devId:" + this.getDevAddr() + " <-- ");//debug log
        UU.printData(result);
        return  addCheckAndSendEmail(result,sendData,0,2,2,true);
    }
     // 增加校验、返回数据、发送邮件的方法
    public byte[] addCheckAndSendEmail(byte[] result,byte[] sendData,int ix,int len,int head,boolean b){
        boolean markCheck=false;
        boolean crcCheck=false;
        // 检查发送数据与接收数据的地址及功能码是否一致
        if (result.length>=head){
            byte[] markSendData=ByteUtil.subData(sendData,ix,len);  //截取输出指令len位
            byte[] markResultData=ByteUtil.subData(result,ix,len);   //截取返回结果len位
            markCheck= Arrays.equals(markSendData,markResultData);
            if(b){
                // 再检查返回数据指令的crc校验码是否正确
                byte[] resultFront=ByteUtil.subData(result,0,result.length-2);
                byte[] crcResultFront=UU.getCrc16Btye(resultFront);
                crcCheck=Arrays.equals(crcResultFront,ByteUtil.subData(result,result.length-2,2));
                if(markCheck&&crcCheck){
                    //输出结果
                    System.out.print("devId:" + this.getDevAddr() + " --> ");//debug log
                    UU.printData(result);
                    return result;   //正常结果
                }else{
                    return returnExceptionNullDataAndSendEmail(this.getDevAddr(),result);
                }
            }else{
                if(markCheck&&sendData[6]==result[6]&&sendData[7]==result[7]&&
                        result[5]==ByteUtil.subData(result,6,result.length-6).length){
                    //输出结果
                    System.out.print("devId:" + this.getDevAddr() + " --> ");//debug log
                    UU.printData(result);
                    return result;   //正常结果
                }else{
                    return returnExceptionNullDataAndSendEmail(this.getDevAddr(),result);
                }
            }
        }else {
            return returnExceptionNullDataAndSendEmail(this.getDevAddr(),result);
            }
        }

    // 返回异常数据或无返回数据并发邮件
    public byte[] returnExceptionNullDataAndSendEmail(String devAddr,byte[] result){
        Date date = new Date();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(result.length<=0){
            System.out.print("devId:" + this.getDevAddr() + " --> 设备没有返回数据");
            UU.printData(result);
            content ="时间："+dateFormat.format(date)+",地址为：" + this.getDevAddr() + "的设备没有返回数据！";
        }else{
            System.out.print("devId:" + devAddr + " --> 返回数据异常！");
            UU.printData(result);
            content = dateFormat.format(date)+":地址为" + this.getDevAddr() + "的设备返回异常数据！";
        }
        if(judgeOverTime(this.getDevAddr())){
            // sendEmail(this.getDevAddr(),content);
        }
        return null;
    }
    // 一次发邮件之后，判断是否超过18小时
    public boolean judgeOverTime(String devAddr){
        if (timeStore.get(devAddr) == null) {
            return true;
        } else {
            long recordTime = timeStore.get(devAddr);
            if(System.currentTimeMillis()>=recordTime){
                return true;
            }else{
                return false;
            }
        }
    }
    //发送邮件的方法
    public void sendEmail(String devAddr,String content){
        timeStore.put(devAddr,System.currentTimeMillis() + 1000 * 60 * 60 * 18);   // 18小时
                    try {
                    MailOperation.sendMail(USER, PASSWORD, HOST, FROM, TO, SUBJECT, content);  //发邮件
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.out.println("邮件未发送成功！");
                    }
                }

    //	public byte[] getDataRtu(Integer startAddr, Integer len) throws IOException {
//		IntNum startAddrNum = new IntNum(startAddr);
//		IntNum lenNUmum = new IntNum(len);
//
//		byte[] result = {};
//
//		byte[] sendData = new byte[6];
//
//		sendData[0] = this.devID.byteValue();
//		sendData[1] = 3;
//		sendData[2] = startAddrNum.h2();
//		sendData[3] = startAddrNum.l2();
//		sendData[4] = lenNUmum.h2();
//		sendData[5] = lenNUmum.l2();
//
//		byte[] sendDataHasCRC = U.setCrc16Btye(sendData);
//
//		System.out.print("devId:" + this.getDevAddr() + " <-- ");//debug log
//		U.printData(sendDataHasCRC);
//		//		this.wk.send(sendData);
////		result = this.wk.read4TimeOut();
//
//		result = this.wk.command(sendDataHasCRC);
//
//		System.out.print("devId:" + this.getDevAddr() + " --> bytes>");//debug log
//		U.printData(result);
//
//
//		return result;
//	}
    public byte[] setDataRtu(Integer startAddr, Integer value) throws IOException {
        return setDataRtu(startAddr, value, 6);
    }

    public byte[] setDataRtu(Integer startAddr, Integer value, Integer cmdCode) throws IOException {
        IntNum startAddrNum = new IntNum(startAddr);
        IntNum valueNUmum = new IntNum(value);

        byte[] result = {};

        byte[] sendData = new byte[6];

        sendData[0] = this.devID.byteValue();
        sendData[1] = cmdCode.byteValue();
        sendData[2] = startAddrNum.h2();
        sendData[3] = startAddrNum.l2();
        sendData[4] = valueNUmum.h2();
        sendData[5] = valueNUmum.l2();

        byte[] sendDataHasCRC = UU.setCrc16Btye(sendData);

        System.out.print("devId:" + this.getDevAddr() + " <-- ");//debug log
        UU.printData(sendDataHasCRC);
        //		this.wk.send(sendData);
//		result = this.wk.read4TimeOut();

        result = this.wk.commandHasProi(sendDataHasCRC, 1);

        System.out.print("devId:" + this.getDevAddr() + " --> ");//debug log
        UU.printData(result);


        return result;
    }

    protected IntNum cnt = new IntNum(1);

    public byte[] getDataTcp(Integer startAddr, Integer len) throws IOException{
        return getDataTcp(startAddr,len,3);
    }
    //起始读取地址和读取长度
    public byte[] getDataTcp(Integer startAddr, Integer len,Integer cmdCode) throws IOException {

        IntNum startAddrNum = new IntNum(startAddr);
        IntNum lenNUmum = new IntNum(len);

        byte[] result = {};

        byte[] sendData = new byte[12];

        sendData[0] = cnt.l2();
        sendData[1] = cnt.h2();
        sendData[2] = 0;
        sendData[3] = 0;
        sendData[4] = 0;
        sendData[5] = 6;

        sendData[6] = this.devID.byteValue();
        sendData[7] = cmdCode.byteValue();
        sendData[8] = startAddrNum.h2();
        sendData[9] = startAddrNum.l2();
        sendData[10] = lenNUmum.h2();
        sendData[11] = lenNUmum.l2();

        System.out.print("devId:" + this.getDevAddr() + " <-- ");  //debug log
        UU.printData(sendData);

//		this.wk.send(sendData);
//		result = this.wk.read4TimeOut();

        result = this.wk.command(sendData);
        System.out.print("devId:" + this.getDevAddr() + " <-- ");  //debug log
        UU.printData(result);
        return  addCheckAndSendEmail(result,sendData,0,5,5,false);
    }

    public void setData(Integer startAddr, Integer value) throws IOException {
        byte[] orgData = this.setDataRtu(startAddr, value);
    }

    public byte[] getData(Integer startAddr, Integer len, Integer cmdCode) throws IOException {
        byte[] orgData = this.getDataRtu(startAddr, len,cmdCode);

        if (orgData.length < 1) return null;
        byte[] databuf = ByteUtil.subData(orgData, 3, len.intValue());
        return databuf;
    }

    public Short getShortData(Integer startAddr, Integer cmdCode) throws IOException {
        Short result = null;
        byte[] databuf = this.getData(startAddr.intValue(), 2, cmdCode);
        databuf = ByteUtil.reverse(databuf);
        result = ByteUtil.getShort(databuf);

        return result;
    }

    public Float getFloatData(Integer startAddr, Integer len, Integer cmdCode) throws IOException {
        Float result = null;
        byte[] databuf = this.getData(startAddr.intValue(), 2, cmdCode);
        databuf = ByteUtil.reverse(databuf);
        databuf = ByteUtil.reverse(databuf);
        result = ByteUtil.getFloat(databuf);
        return result;
    }

    public Integer getIntData(Integer startAddr, Integer len, Integer cmdCode) throws IOException {
        Integer result = null;
        byte[] databuf = this.getData(startAddr.intValue(), 2, cmdCode);
        databuf = ByteUtil.reverse(databuf);
        databuf = ByteUtil.reverse2Byte(databuf);
        databuf = ByteUtil.reverse(databuf);
        result = ByteUtil.getInt(databuf);
        return result;
    }

    public Long getLongData(Integer startAddr, Integer len, Integer cmdCode) throws IOException {
        Long result = null;
        byte[] databuf = this.getData(startAddr.intValue(), 2, cmdCode);
        databuf = ByteUtil.reverse(databuf);
        result = ByteUtil.getLong(databuf);
        return result;
    }
}
